import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:connectivity/connectivity.dart';
import 'package:date_format/date_format.dart';
import '../../config/config.dart';
import '../../app_files.dart';

///请求消息头设置
class HeaderInterceptors extends InterceptorsWrapper {
  @override
  onRequest(RequestOptions options) async {
    ///超时
    options.connectTimeout = 20000;
    options.receiveTimeout = 20000;
    options.responseType = ResponseType.json;
    options.contentType = "application/json";
    return options;
  }
}

///请求前网络判断
class ErrorInterceptors extends InterceptorsWrapper {
  final Dio _dio;

  ErrorInterceptors(this._dio);

  @override
  onRequest(RequestOptions options) async {
    //没有网络
    var connectivityResult = await (new Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.none) {
      DioError err = DioError()
        ..response = null
        ..type = DioErrorType.DEFAULT
        ..error = "网络异常,请检查联网情况";
      throw (err);
    }
    return options;
  }
}

///打印日志
class LogsInterceptors extends InterceptorsWrapper {
  @override
  onRequest(RequestOptions options) async {
    if (true) {
      print("请求url：${options.path}");
//      print('请求头: ' + options.headers.toString());
      if (options.data != null) {
        print('请求参数: ' + options.data.toString());
      }
    }
    return options;
  }

  @override
  onResponse(Response response) async {
    if (true) {
      if (response != null) {
        print('返回参数: ' + response.toString());
      }
    }
    return response; // continue
  }

  @override
  onError(DioError err) async {
    if (true) {
      print('请求异常: ' + err.toString());
      print('请求异常信息: ' + err.response?.toString() ?? "");
      if (err.response.data['msg'] == 'token已过期') {
        bus.emit('errlogin');
      }
    }
    err.error = "服务器返回错误";
    return err;
  }
}

class HttpTool {
  Dio _dio = new Dio(); // 使用默认配置

  HttpTool() {
    _dio.interceptors.add(new HeaderInterceptors());

    _dio.interceptors.add(new LogsInterceptors());

    _dio.interceptors.add(new ErrorInterceptors(_dio));
  }

  ///发起网络请求
  ///[ url] 请求url
  ///[ params] 请求参数
  ///[ header] 外加头
  ///[ option] 配置
  netFetch(
    url,
    params, {
    method = "post",
    appendUrl = NetworkConfig.httpUr_v1,
    Map<String, dynamic> header,
  }) async {
    try {
      if (!url.toString().startsWith('http')) url = appendUrl + url;
      Map<String, dynamic> requestHeader = Map();
      requestHeader['RequestDomain'] = NetworkConfig.hostUrl;

      if (header != null)
        requestHeader.addAll(header);
      else
        requestHeader['access-token'] =
            GlobalStore.store.getState().userInfo.token;
      Response res = await _dio.request(url,
          data: params,
          options: Options(
            method: method,
            headers: requestHeader,
            contentType: 'application/json',
          ));
      Map response;
      if (res.data is Map) {
        response = res.data;
      } else {
        response = json.decode(res.data);
      }

      if (response["ResultCode"].toString() == "0" ||
          response["Code"].toString() == "0") {
        return response["Data"];
      } else {
        if (response["Message"].toString() == ThemeConfig.errDesc_login) {
          bus.emit('errlogin');
        }
        DioError err = DioError()
          ..response = res
          ..type = DioErrorType.DEFAULT
          ..error = response["Message"].toString() == ThemeConfig.errDesc_login
              ? ''
              : response["Message"].toString();
        return err;
      }
    } catch (e) {
      DioError err = DioError();
      if (e is! DioError) {
        print('$e');
        err.error = "解析失败";
      } else {
        DioError ers = e;
        err.error = ers.message;
        if (ers.type == DioErrorType.CONNECT_TIMEOUT ||
            ers.type == DioErrorType.RECEIVE_TIMEOUT) {
          err.error = "连接超时";
        } else {
          err.error = '网络链接错误';
        }
      }
      return err;
    }
  }

  requestUrl(url, params, {method = "post"}) async {
    try {
      Response res = await _dio.request(url,
          data: params, options: Options(method: method));
      Map response = json.decode(res.data);
      return response;
    } catch (e) {
      DioError err = DioError();
      if (e is! DioError) {
        err.error = "解析失败";
      } else {
        DioError ers = e;
        err.error = ers.message;
        if (ers.type == DioErrorType.CONNECT_TIMEOUT ||
            ers.type == DioErrorType.RECEIVE_TIMEOUT) {
          err.error = "连接超时";
        }
      }
      return err;
    }
  }

  formData(
    url,
    File file, {
    method = "post",
    Map<String, dynamic> params,
    String fileName,
    header,
  }) async {
    DateTime dateTime = DateTime.now();

//    String fileName = formatDate(dateTime, [yyyy, '', mm, '', dd]);
    String finalName = fileName ?? '${dateTime.millisecondsSinceEpoch}.jpeg';
    print('------------ upload fileName:$fileName');
    Map<String, dynamic> map = Map();
    if (params != null && params.length > 0) map.addAll(params);
    map.addAll({
      "imgFiles": await MultipartFile.fromFile(
        file.path,
        filename: finalName,
      )
    });

    FormData formData = FormData.fromMap(map);

    return await netFetch(url, formData, header: header);
  }

  formSteam(
    url,
    List<int> file, {
    method = "post",
    Map<String, dynamic> params,
    String fileName,
  }) async {
    DateTime dateTime = DateTime.now();

//    String fileName = formatDate(dateTime, [yyyy, '', mm, '', dd]);
    String finalName = fileName ?? '${dateTime.millisecondsSinceEpoch}.jpeg';
    print('------------ upload fileName:$fileName');
    Map<String, dynamic> map = Map();
    if (params != null && params.length > 0) map.addAll(params);
    map.addAll({
      "imgFiles": MultipartFile.fromBytes(
        file,
        filename: finalName,
      )
    });

    FormData formData = FormData.fromMap(map);

    return await staffPost(url, formData);
  }

  postData(
    url,
    params, {
    method = "post",
    appendUrl = NetworkConfig.httpUr_v1,
    header,
  }) async {
//    String json = jsonEncode(params);
    return await netFetch(url, params);
  }

  formStream(url, List<int> file,
      {method = "post", Map<String, dynamic> params}) async {
    DateTime dateTime = DateTime.now();

    String fileName = formatDate(dateTime, [yyyy, '', mm, '', dd]);
    fileName += '.jpeg';
    Map<String, dynamic> map = Map();
    if (params != null && params.length > 0) map.addAll(params);
    map.addAll({
      "file": MultipartFile.fromBytes(file, filename: fileName),
    });

    FormData formData = FormData.fromMap(map);

    return await netFetch(url, formData);
  }

  static void post(String url, Map<String, dynamic> pamars,
      Function(Map response) succss, Function(dynamic error) faild) async {
    try {
      var res = await httpTool.netFetch(url, pamars);
      succss(res);
    } catch (e) {
      if (e is DioError) {
        faild(e);
      } else {
        print("请求失败:解析失败！");
        DioError err = DioError()
          ..response = null
          ..type = DioErrorType.DEFAULT
          ..error = "服务器返回错误";
        faild(err);
      }
    }
  }

  staffPost(
    url,
    params, {
    method = "post",
    appendUrl = NetworkConfig.staff_HttpUrl,
    Map<String, dynamic> header,
  }) async {
    try {
      if (url.length > 7 && url.substring(0, 7) != 'http://') {
        url = appendUrl + url;
      } else {
        url = appendUrl + url;
      }
      Map<String, dynamic> requestHeader = Map();

      if (header != null)
        requestHeader.addAll(header);
      else {
        if (GlobalStore.store.getState().userInfo.token.isNotEmpty)
          requestHeader['token'] = GlobalStore.store.getState().userInfo.token;
      }
      Response res = await _dio.request(url,
          data: params,
          options: Options(
            method: method,
            headers: requestHeader,
            contentType: 'application/json',
          ));
      Map response;
      if (res.data is Map) {
        response = res.data;
      } else {
        response = json.decode(res.data);
      }

      if (response["code"].toString() == "0") {
        return response;
      } else {
        if (response["msg"].toString() == 'token已过期') {
          bus.emit('errlogin');
        }
        DioError err = DioError()
          ..response = res
          ..type = DioErrorType.DEFAULT
          ..error = response["msg"].toString() == ThemeConfig.errDesc_login
              ? ''
              : response["msg"].toString();
        return err;
      }
    } catch (e) {
      DioError err = DioError();
      if (e is! DioError) {
        print('$e');
        err.error = "解析失败";
      } else {
        DioError ers = e;
        err.error = ers.message;
        if (ers.type == DioErrorType.CONNECT_TIMEOUT ||
            ers.type == DioErrorType.RECEIVE_TIMEOUT) {
          err.error = "连接超时";
        } else {
          print(ers.type);
          err.error = '网络链接错误';
        }
      }
      return err;
    }
  }

  staffFormData(
    url,
    File file, {
    method = "post",
    Map<String, dynamic> params,
    String fileName,
  }) async {
    DateTime dateTime = DateTime.now();

//    String fileName = formatDate(dateTime, [yyyy, '', mm, '', dd]);
    String finalName = fileName ?? '${dateTime.millisecondsSinceEpoch}.jpeg';
    print('------------ upload fileName:$fileName');
    Map<String, dynamic> map = Map();
    if (params != null && params.length > 0) map.addAll(params);
    map.addAll({
      "file": await MultipartFile.fromFile(
        file.path,
        filename: finalName,
      )
    });

    FormData formData = FormData.fromMap(map);

    return await staffPost(url, formData);
  }
}

final HttpTool httpTool = new HttpTool();
